package org.example.doctorapi.controller;

import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentParser;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.parser.apache.tika.ApacheTikaDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentByParagraphSplitter;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
import dev.langchain4j.store.embedding.EmbeddingSearchResult;
import dev.langchain4j.store.embedding.EmbeddingStore;
import org.example.doctorapi.data.FileInfoMent;
import org.example.doctorapi.mapper1.FileInfoMapper;
import org.example.doctorapi.minio.MinioConfigCommon;
import org.example.doctorapi.minio.MinoUtil;
import org.example.doctorcommon.util.BaseResult;
import org.example.doctorapi.server.ChatAssistantFlux;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;
import java.util.List;

import static dev.langchain4j.store.embedding.filter.MetadataFilterBuilder.metadataKey;

@RestController
@RequestMapping("/chat")
public class ChatController {
    @Autowired
    @Qualifier("StreamingChatAssistant")
    private ChatAssistantFlux chatAssistantFlux;
    @Autowired
    @Qualifier("ChatLanguageModelImage")
    private ChatLanguageModel chatLanguageModelImage;
    @Autowired
    private FileInfoMapper fileInfoMapper;
    @Autowired
    private MinoUtil minoUtil;
    @Autowired
    private MinioConfigCommon minioConfigCommon;
    @Autowired
    @Qualifier("MyEmbeddingModel")
    private EmbeddingModel embeddingModel;
    @Autowired
    EmbeddingStore<TextSegment> embeddingStore;


    @GetMapping("/ai/generate")
    public Flux<String> chat(@RequestParam(value = "message",defaultValue = "who say give me eat every day? tell me why?") String message) {
        return chatAssistantFlux.chat(message);
    }

    /**
     * 照片Ai模型
     * @param msg 描述
     * @param file 照片文件
     * @return 返回描述
     * @throws IOException 返回异常
     */
    @PostMapping("/image")
    public String getImage(String msg,MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        byte[] byteArray = inputStream.readAllBytes();
        String encodeToString = Base64.getEncoder().encodeToString(byteArray);
        UserMessage userMessage = UserMessage.from(
                TextContent.from(msg),
                ImageContent.from(encodeToString, "image/png")
        );
        Response<AiMessage> response = chatLanguageModelImage.generate(userMessage);
        return response.content().text();
    }

    /*url连接*/
    @GetMapping("/fileUrl")
    public BaseResult urlSearch(String fileUrl,String username) throws Exception{
        // String fileUrl = "http://192.168.66.99:19000/admintest/李锦堂个人简历.docx";
        /**
         * DocumentByParagraphSplitter: 按段落拆分
         * DocumentBySentenceSplitter: 按句子拆分
         * DocumentByWordSplitter: 按单词拆分
         * DocumentByCharacterSplitter: 按字符拆分
         * DocumentByRegexSplitter: 按正则表达式拆分
         */
        HttpURLConnection httpUrl = (HttpURLConnection) new URL(fileUrl).openConnection();
        httpUrl.connect();
        System.out.println("httpUrl"+httpUrl);
        InputStream inputStream = httpUrl.getInputStream();
        DocumentParser parser = new ApacheTikaDocumentParser();
        Document parse = parser.parse(inputStream);
        // 按段落拆分
        DocumentSplitter documentSplitter = new DocumentByParagraphSplitter(200,3);
        List<TextSegment> split = documentSplitter.split(parse);
        /*TextSegment from1 = TextSegment.from("客服的电话是400-3464563");*/
        for (TextSegment textSegment : split) {
            textSegment.metadata().put("author",username);
            Embedding content1 = embeddingModel.embed(textSegment).content();
            embeddingStore.add(content1,textSegment);
        }
        inputStream.close();
        return BaseResult.ok("成功插入向量数据库");
    }
    @GetMapping("/searchQdrant")
    public BaseResult searchQdrant(String username, String message){
        Embedding embedding = embeddingModel.embed(message).content();
        EmbeddingSearchRequest request = EmbeddingSearchRequest.builder()
                .maxResults(1)
                .filter(metadataKey("author").isEqualTo(username))
                .queryEmbedding(embedding)
                .build();
        EmbeddingSearchResult<TextSegment> search = embeddingStore.search(request);
        EmbeddingMatch<TextSegment> match = search.matches().get(0);
        /*System.out.println("match:"+match.embedded().text());*/
        return BaseResult.ok(match.embedded().text());
    }

    @PostMapping("/upload")
    public BaseResult uploadCommon(MultipartFile file) throws IOException {
        //文件名
        String fileName = file.getOriginalFilename();
        long fileSize = file.getSize();
        int charCount = getCharCount(file); // 获取文件字符数
        int segments = calculateSegments(fileSize); // 根据文件大小计算分段数
        // String newFileName = System.currentTimeMillis() + "." + StringUtils.substringAfterLast(fileName, ".");
        //类型
        String contentType = file.getContentType();
        try {
            InputStream minoUtilObject = minoUtil.getObject(minioConfigCommon.getBucketName(), fileName);
            if (minoUtilObject.readAllBytes() != null) return BaseResult.ok("文件存在");
        }catch (Exception e){
            System.out.println("查询文件");
        }
        minoUtil.uploadFile(minioConfigCommon.getBucketName(), file, fileName, contentType);
        FileInfoMent fileInfoMent = new FileInfoMent();
        fileInfoMent.setFileName(fileName);
        String s = minioConfigCommon.getEndpoint()+ "/" + minioConfigCommon.getBucketName() + "/" + file.getOriginalFilename();
        fileInfoMent.setFilePath(s);
        fileInfoMent.setCharCount(charCount);
        fileInfoMent.setSegments(segments);
        fileInfoMapper.insert(fileInfoMent);
        return BaseResult.ok("上传成功");
    }
    // 计算字符数（根据需要，可能是文本文件解析）
    private int getCharCount(MultipartFile file) throws IOException {
        String content = new String(file.getBytes());
        return content.length();
    }

    // 根据文件大小计算分段数，假设每段为 5MB
    private int calculateSegments(long fileSize) {
        final long segmentSize = 5 * 1024 * 1024; // 5MB
        return (int) Math.ceil((double) fileSize / segmentSize);
    }

    @GetMapping("/getList")
    public List<FileInfoMent> select() {
        return fileInfoMapper.selectList(null);
    }

}
